 /*
  * Copyright (C), weixin.zhu
  * FileName: JavaMailUtils
  * Author:   weixin.zhu
  * Date:     2021/2/26 11:42
  * Description: 发送邮件工具类
  * History:
  * <author>          <time>          <version>          <desc>
  * 作者姓名           修改时间           版本号              描述
  */
 package com.ruoyi.common.utils;

 import com.ruoyi.common.config.MailConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

 import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 import javax.mail.*;
 import javax.mail.Message.RecipientType;
 import javax.mail.internet.*;
 import java.io.UnsupportedEncodingException;
 import java.util.Date;
 import java.util.Properties;
 import java.util.TimerTask;

 /**
  * 〈一句话功能简述〉<br>
  * 〈发送邮件工具类〉
  *
  * @author weixin.zhu
  * @create 2021/2/26
  */
 public class JavaMailUtils {
     private static final Logger log = LoggerFactory.getLogger(JavaMailUtils.class);

     private volatile static Properties mailProperties = null;
     public static final String EMAIL_CONTENT_TYPE__HTML = "text/html;charset=utf-8";
     @SuppressWarnings("unused")
     public static final String EMAIL_CONTENT_TYPE__TEXT = "text/plain;charset=utf-8";

     public static Properties getMailProperties() {
         if (!MailConfig.isSwitchTurnOn()) {
             return null;
         }
         if (mailProperties == null) {
             synchronized (JavaMailUtils.class) {
                 if (mailProperties == null) {
                     //跟smtp服务器建立一个连接
                     mailProperties = new Properties();
                     //设置邮件服务器主机名
                     mailProperties.setProperty("mail.host", MailConfig.getHost());
                     //发送服务器需要身份验证,要采用指定用户名密码的方式去认证
                     mailProperties.setProperty("mail.smtp.auth", "true");
                     //发送邮件协议名称
                     mailProperties.setProperty("mail.transport.protocol", "smtp");

                     mailProperties.put("mail.smtp.ssl.enable", "true");
                     //下面两段代码是设置ssl和端口，不设置发送不出去。
                     mailProperties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
                     //props.setProperty("mail.smtp.port", "465");
                     mailProperties.setProperty("mail.smtp.socketFactory.port", String.valueOf(MailConfig.getPort()));

                     // 发件人的账号
                     mailProperties.put("mail.user", MailConfig.getUsername());
                     // 访问SMTP服务时需要提供的密码
                     mailProperties.put("mail.password", MailConfig.getPassword());
                 }
             }

         }
         return mailProperties;
     }


     private static String getMailList(String[] mailArray) {
         StringBuilder toList = new StringBuilder();
         if(mailArray == null){
             return toList.toString();
         }
         int length = mailArray.length;
         if (length < 2) {
             toList.append(mailArray[0]);
         } else {
             for (int i = 0; i < length; i++) {
                 toList.append(mailArray[i]);
                 if (i != (length - 1)) {
                     toList.append(",");
                 }
             }
         }
         return toList.toString();
     }

     //添加多个附件
     public static void addArchives(String[] fileList, Multipart multipart) throws MessagingException, UnsupportedEncodingException {
         for (String s : fileList) {
             MimeBodyPart mailArchive = new MimeBodyPart();
             FileDataSource fds = new FileDataSource(s);
             mailArchive.setDataHandler(new DataHandler(fds));
             mailArchive.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B"));
             multipart.addBodyPart(mailArchive);
         }
     }

     /**
      * 发送邮件工具类:邮件发送,因为具有ssl加密,采用的是smtp协议
      *
      * @param to               收件人
      * @param cc               抄送人
      * @param bcc              密送人
      * @param emailSubject     邮件的主题
      * @param emailContent     邮件的内容
      * @param fileList         邮件附件
      * @param emailContentType 邮件内容的类型,支持纯文本:"text/plain;charset=utf-8";,带有Html格式的内容:"text/html;charset=utf-8"
      * @return 成功为1，失败为0，开关关闭为-1
      */
     public static int sendEmail(String[] to, String[] cc, String[] bcc, String emailSubject, String emailContent, String[] fileList, String emailContentType) {
         int res = 0;
         if (!MailConfig.isSwitchTurnOn()) {
             log.info("Email send fail! Email send switchFlag is not 'Y'!");
             return -1;
         }
         try {
             // 构建授权信息，用于进行SMTP进行身份验证
             Authenticator authenticator = new Authenticator() {
                 @Override
                 protected PasswordAuthentication getPasswordAuthentication() {
                     // 用户名、密码
                     String userName = getMailProperties().getProperty("mail.user");
                     String password = getMailProperties().getProperty("mail.password");
                     return new PasswordAuthentication(userName, password);
                 }
             };
             // 创建session
             Session mailSession = Session.getInstance(getMailProperties(), authenticator);
             // 设置打开调试状态
             if (MailConfig.isDebugTurnOn()) {
                 mailSession.setDebug(true);
             }
             // 声明一个Message对象(代表一封邮件),从session中创建
             MimeMessage msg = new MimeMessage(mailSession);

             //可以发送几封邮件:可以在这里 for循环多次
             //邮件信息封装
             // 1 发件人
             msg.setFrom(new InternetAddress(getMailProperties().getProperty("mail.user")));

             // 1.1 发送
             if (to != null) {
                 String toList = getMailList(to);
                 InternetAddress[] iaToList = InternetAddress.parse(toList);
                 msg.setRecipients(RecipientType.TO, iaToList); // 收件人
             }
             // 1.2 抄送
             if (cc != null) {
                 String toListcc = getMailList(cc);
                 InternetAddress[] iaToListcc = InternetAddress.parse(toListcc);
                 msg.setRecipients(RecipientType.CC, iaToListcc); // 抄送人
             }
             // 1.3 密送
             if (bcc != null) {
                 String toListbcc = getMailList(bcc);
                 InternetAddress[] iaToListbcc = InternetAddress.parse(toListbcc);
                 msg.setRecipients(RecipientType.BCC, iaToListbcc); // 密送人
             }
             // 2 邮件内容:主题、内容、附件
             if (fileList != null) {
                 MimeMultipart multipart = new MimeMultipart();

                 //正文部分
                 BodyPart messageBodyPart = new MimeBodyPart();
                 messageBodyPart.setContent(emailContent, emailContentType);
                 multipart.addBodyPart(messageBodyPart);
                 //增加附件 注,测试时用163邮箱发邮件，部分文件类型可能会导致发送失败，报错信息类似：smtplib.SMTPDataError: (554, 'DT:SPM 163 smtp
                 addArchives(fileList, multipart);

                 multipart.setSubType("related");//关联关系
                 msg.setSubject(emailSubject);
                 msg.setContent(multipart);
                 msg.setSentDate(new Date());
                 msg.saveChanges();
             } else {
                 msg.setSubject(emailSubject);
                 // msg.setContent("Hello, 我是debug!!!", );//纯文本
                 msg.setContent(emailContent, emailContentType);//发html格式的文本
             }

             // 发送动作
             Transport.send(msg);
             log.info("邮件发送成功");
             res = 1;

         } catch (Exception e) {
             log.error(ExceptionUtil.getExceptionMessage(e));
             //res = 0;
         }
         return res;
     }

     public static int sendEmail(String[] to, String emailSubject, String emailContent) {
         return sendEmail(to, null, null, emailSubject, emailContent, null, EMAIL_CONTENT_TYPE__HTML);
     }

     public static int sendEmail(String to, String emailSubject, String emailContent) {
         return sendEmail(new String[]{to}, null, null, emailSubject, emailContent, null, EMAIL_CONTENT_TYPE__HTML);
     }

     /**
      * 异步发送邮件任务
      */
     public static TimerTask sendEmailAsync(String to,String title,String content)
     {
         return new TimerTask()
         {
             @Override
             public void run()
             {
                 int res = JavaMailUtils.sendEmail(to,title,content);
                 log.info("\n发送结果:" + res);
             }
         };
     }
 }